package utils

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
)

type Request struct {
	Method         string
	UrlSource      string
	ReqestHeaders  map[string]string
	RequestBody    map[string]string
	RequestCookies []http.Cookie
	Timeout        time.Duration
	ForbidRedirect bool
	Proxy          string

	ResponseCookies []*http.Cookie
	ResponseHeader  map[string][]string
}

func NewRequest(method string, urlSource string, reqestHeaders map[string]string, requestBody map[string]string, requestCookies []http.Cookie, timeout time.Duration, forbidRedirect bool, proxy string) *Request {
	return &Request{
		Method:         method,
		UrlSource:      urlSource,
		ReqestHeaders:  reqestHeaders,
		RequestBody:    requestBody,
		RequestCookies: requestCookies,
		Timeout:        timeout,
		ForbidRedirect: forbidRedirect,
		Proxy:          proxy,
	}
}

// 对象请求方式
func (request *Request) SendRequest() (data []byte, err error) {
	defer func() {
		r := recover()
		if r != nil {
			fmt.Println("请求地址出错:", r)
			fmt.Println("出错地址:", request.UrlSource)
			data = []byte("")
			err = errors.New("请求地址出错:" + request.UrlSource)
		}
	}()
	//proxy = "http://127.0.0.1:22307"
	request.UrlSource = strings.TrimSpace(request.UrlSource)
	urlRegex := regexp.MustCompile(`^(https?|http)://[^\s/$.?#].[^\s]*$`)
	if !urlRegex.MatchString(request.UrlSource) {
		return []byte{}, errors.New("地址输入有误")
	}
	urlSourceParse, urlSourceParseErr := url.Parse(request.UrlSource)
	if urlSourceParseErr != nil {
		return []byte{}, errors.New("地址输入有误")
	}
	// 检查 Scheme 和 Host 是否为空，以确认 URL 是否有效
	if urlSourceParse.Scheme == "" || urlSourceParse.Host == "" {
		return []byte{}, errors.New("地址输入有误")
	}

	request.Method = strings.ToUpper(request.Method)
	rawBodyParams := url.Values{}
	for key, value := range request.RequestBody {
		rawBodyParams.Set(key, value)
	}
	rawBody := rawBodyParams.Encode()
	payload := strings.NewReader(rawBody)

	// 创建请求
	req, reqErr := http.NewRequest(request.Method, request.UrlSource, payload)
	if reqErr != nil {
		return data, reqErr
	}

	// 设置头部
	for key, value := range request.ReqestHeaders {
		req.Header.Set(key, value)
	}

	// 设置 Cookie
	for _, cookie := range request.RequestCookies {
		req.AddCookie(&cookie)
	}
	// 发送请求
	client := &http.Client{}
	client.Timeout = request.Timeout //30 * time.Second // 设置超时时间为 10 秒

	if request.Proxy != "" {
		proxyURL, err := url.Parse(request.Proxy)
		if err != nil {
			fmt.Println("解析代理地址时出错:", err)
			return data, err
		}

		// 创建 Transport 对象并设置代理
		transport := &http.Transport{
			Proxy: http.ProxyURL(proxyURL),
		}
		client.Transport = transport
	}
	if request.ForbidRedirect {
		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		}
	}

	resp, respErr := client.Do(req)
	if respErr != nil {
		return data, respErr
	}
	defer resp.Body.Close()

	// 读取响应内容
	respBody, respBodyErr := io.ReadAll(resp.Body)
	if respBodyErr != nil {
		return data, respBodyErr
	}
	request.ResponseHeader = resp.Header
	request.ResponseCookies = resp.Cookies()
	return respBody, nil
}

// 方法请求方式
func SendRequest(method string, urlSource string, headers map[string]string, body map[string]string, cookies []*http.Cookie, timeout time.Duration, forbidRedirect bool, proxy string) (data []byte, err error) {
	defer func() {
		r := recover()
		if r != nil {
			fmt.Println("请求地址出错:", r)
			fmt.Println("出错地址:", urlSource)
			data = []byte("")
			err = errors.New("请求地址出错:" + urlSource)
		}
	}()
	//proxy = "http://127.0.0.1:22307"
	urlSource = strings.TrimSpace(urlSource)
	urlRegex := regexp.MustCompile(`^(https?|http)://[^\s/$.?#].[^\s]*$`)
	if !urlRegex.MatchString(urlSource) {
		return []byte{}, errors.New("地址输入有误")
	}
	urlSourceParse, urlSourceParseErr := url.Parse(urlSource)
	if urlSourceParseErr != nil {
		return []byte{}, errors.New("地址输入有误")
	}
	// 检查 Scheme 和 Host 是否为空，以确认 URL 是否有效
	if urlSourceParse.Scheme == "" || urlSourceParse.Host == "" {
		return []byte{}, errors.New("地址输入有误")
	}

	method = strings.ToUpper(method)
	rawBodyParams := url.Values{}
	for key, value := range body {
		rawBodyParams.Set(key, value)
	}
	rawBody := rawBodyParams.Encode()
	payload := strings.NewReader(rawBody)

	// 创建请求
	req, reqErr := http.NewRequest(method, urlSource, payload)
	if reqErr != nil {
		return data, reqErr
	}

	// 设置头部
	for key, value := range headers {
		req.Header.Set(key, value)
	}

	// 设置 Cookie
	for _, cookie := range cookies {
		req.AddCookie(cookie)
	}
	// 发送请求
	client := &http.Client{}
	client.Timeout = timeout //30 * time.Second // 设置超时时间为 10 秒

	if proxy != "" {
		proxyURL, err := url.Parse(proxy)
		if err != nil {
			fmt.Println("解析代理地址时出错:", err)
			return data, err
		}

		// 创建 Transport 对象并设置代理
		transport := &http.Transport{
			Proxy: http.ProxyURL(proxyURL),
		}
		client.Transport = transport
	}
	if forbidRedirect {
		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		}
	}

	resp, respErr := client.Do(req)
	if respErr != nil {
		return data, respErr
	}
	defer resp.Body.Close()

	// 读取响应内容
	respBody, respBodyErr := io.ReadAll(resp.Body)
	if respBodyErr != nil {
		return data, respBodyErr
	}
	return respBody, nil
}
